#pragma once

#include <jlib/jlib.h>
#include <unordered_map>

struct GLFWwindow;
struct GLFWView : public jlib::GLView {

  GLFWView (const GLFWView&) noexcept = delete;
  GLFWView& operator= (const GLFWView&) noexcept = delete;

  bool createWindow (Listener *listener, const WindowConfig& config) override;
  void pollEvents () override;
  void swapBuffers () override;
  void destroyWindow () override;

  inline static GLFWView* instance () noexcept {
    static GLFWView view;
    return &view;
  }

private:
  GLFWView ();
  ~GLFWView () override = default;

  static void onError (int error, const char* info);
  static void onWindowPos (GLFWwindow*, int x, int y);
  static void onWindowSize (GLFWwindow*, int w, int h);
  static void onWindowClose (GLFWwindow*);
  static void onWindowFocus (GLFWwindow*, int focused);
  static void onWindowIconify (GLFWwindow*, int iconified);
  static void onFramebufferSize (GLFWwindow*, int w, int h);
  static void onMouseButton (GLFWwindow*, int button, int action, int mods);
  static void onCursorPos (GLFWwindow*, double x, double y);
  static void onCursorEnter (GLFWwindow*, int entered);
  static void onScroll (GLFWwindow*, double x, double y);
  static void onKey (GLFWwindow*, int key, int scancode, int action, int mods);
  static void onChar (GLFWwindow*, unsigned int codepoint);

private:
  GLFWwindow *_window = nullptr;
  Listener *_listener;

  static jlib::KeyEvent::Key __keyMapping[];
  static jlib::MouseEvent::Button __buttonMapping[];
};
